﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using ImageResizer.FileExplorer.Implementations;
using ImageResizer.FileExplorer.Interface;
using ImageResizer.Outputs;
using ImageResizer.Outputs.Destination;
using ImageResizer.Profiles;
using ImageResizer.Properties;

namespace ImageResizer
{
    /// <summary>
    /// Formulaire de saisie des options de redimensionnement pour ALBULLE
    /// </summary>
    public partial class OptionsDeployAlbulle : Form, IOptionsProvider
    {
        #region Private vars
        /// <summary>
        /// Reader du fichier de configuration Albulle 1.2 (et +)
        /// </summary>
        private AlbulleConfigurationFile _configurationFile;

        /// <summary>
        /// Gestionnaire de profiles
        /// </summary>
        private ProfilesManager _profilesManager;

        /// <summary>
        /// Contient la liste des sorties
        /// </summary>
        private List<Output> _selectedOutputs;
        #endregion

        #region Public properties
        /// <summary>
        /// Répertoire initial des photos à copier.
        /// </summary>
        public string InitialDirectoryOfPicturesToCopy { get; set; } 
        #endregion

        #region Interface (public) properties
        /// <summary>
        /// Obtient la liste des sorties voulues
        /// </summary>
        public List<Output> Outputs
        {
            get { return _selectedOutputs; }
        }

        /// <summary>
        /// Obtient le résultat de la boite de dialogue d'options
        /// </summary>
        public OptionsResults Result { get; private set; }

        /// <summary>
        /// Obtient l'objet permettant de manipuler les fichiers
        /// </summary>
        public IFileExplorer FileExplorer { get; private set; }
        #endregion

        #region CTOR
        /// <summary>
        /// CTOR
        /// </summary>
        public OptionsDeployAlbulle()
        {
            InitializeComponent();

            //créé le manager de profiles
            _profilesManager = new ProfilesManager();

            //créé un container des sorties à générer
            _selectedOutputs = new List<Output>();

            //grise les options (tant que le fichier de config d'albulle n'a pas été ouvert)
            groupBoxOptions.Enabled = false;

            //initialisation du bouton par défaut
            Result = OptionsResults.Cancel;
        } 
        #endregion

        #region Private methods
        /// <summary>
        /// Gestion du boutton Browse pour le fichier de configuration d'Albulle
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonBrowseClick(object sender, EventArgs e)
        {
            if (radioButtonLocal.Checked)
            {
                //recherche en mode local
                //on ouvre simplement un OpenFileDialog
                openFileDialog1.FileName = Resources.DefaultAlbulleConfigurationFile;
                openFileDialog1.Filter = Resources.FilterAlbulleConfigFile;
                openFileDialog1.CheckFileExists = true;
                openFileDialog1.Multiselect = false;
                openFileDialog1.Title = Resources.TitleSearchAlbulleConfigurationFile;
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    textBoxOutputPath.Text = openFileDialog1.FileName;
                    LoadAlbulleConfigurationFile(new LocalFileExplorer(), textBoxOutputPath.Text, textBoxOutputPath.Text);
                }
            }
            else
            {
                //recherche en mode FTP
                //on recherche le fichier de config avec l'explorateur FTP
                FTPBrowser ftpbrowser = new FTPBrowser(FTPBrowser.ModeEnum.File);
                if (ftpbrowser.ShowDialog() == DialogResult.OK)
                {
                    textBoxOutputPath.Text = ftpbrowser.SelectedAbsoluteFullPath;
                    LoadAlbulleConfigurationFile(ftpbrowser.FileExplorer, ftpbrowser.SelectedAbsoluteFullPath, ftpbrowser.SelectedRelativeFullPath);
                }
            }
        }

        /// <summary>
        /// Charge le fichier de configuration
        /// </summary>
        /// <param name="fileExplorer">l'objet permettant de manipuler les fichiers</param>
        /// <param name="originalConfigFilename">le fichier d'origine (d'un ftp par exemple)</param>
        /// <param name="downloadableFile">le fichier lisible (= local => fichier ftp à télécharger)</param>
        private void LoadAlbulleConfigurationFile(IFileExplorer fileExplorer, string originalConfigFilename, string downloadableFile)
        {
            try
            {
                //download file (traitement identique, permet de généraliser le code selon que l'on soit en mode local ou FTP)
                string tempConfigFile = Path.GetTempFileName();
                fileExplorer.FileDownload(downloadableFile, tempConfigFile, true); //réalise le téléchargement en FTP ou une copie locale en mode fichier

                //on tente de charger le fichier de config (exception si pb)
                _configurationFile = new AlbulleConfigurationFile(tempConfigFile, originalConfigFilename, fileExplorer.PathSeparator);

                //on charge les albums disponibles
                LoadAlbumComboBox(fileExplorer);

                //sauvegarde de l'objet explorateur de fichiers
                FileExplorer = fileExplorer;

                //on sauvegarde le chemin du fichier de config utilisé
                Settings.Default.AlbulleConfig = originalConfigFilename;
                Settings.Default.Save();

                //on active les options
                groupBoxOptions.Enabled = true;
            }
            catch (Exception e)
            {
                //on affiche le message d'erreur à l'utilisateur
                MessageBox.Show(Resources.Error + e.Message);
                //on grise la partie option
                groupBoxOptions.Enabled = false;
            }
        }

        /// <summary>
        /// Charge la combox des albums
        /// </summary>
        /// <param name="fileExplorer">l'objet permettant d'explorer les fichiers/répertoires</param>
        private void LoadAlbumComboBox(IFileExplorer fileExplorer)
        {
            comboBoxAlbum.Items.Clear();

            FillAlbumComboBox(fileExplorer, _configurationFile.PhotoFolder);
            comboBoxAlbum.Items.Add(Resources.ComboBoxSeparator);
            comboBoxAlbum.Items.Add(Resources.ProcessDialog_ProcessDialog_Load_Nouvel_album___);
        }

        /// <summary>
        /// Remplit une combobox d'album
        /// </summary>
        /// <param name="fileExplorer">l'objet permettant d'explorer les fichiers/répertoires</param>
        /// <param name="relativePath">le chemin relatif de l'album</param>
        private void FillAlbumComboBox(IFileExplorer fileExplorer, string relativePath)
        {
            foreach (string directoryAlbum in fileExplorer.DirectoryListSubDirs(relativePath))
            {
                if (!String.IsNullOrEmpty(relativePath))
                {
                    //on récupère le nom de l'album
                    string foundAlbum = directoryAlbum;
                    //on gère le chemin relatif initial => foundAlbum contient le chemin complet de l'album
                    //cette ligne permet de rendre le traitement qui suit générique selon le mode local ou FTP
                    //le mode ftp donne un chemin relatif, le mode local donne un chemin absolu
                    if (!directoryAlbum.Contains(relativePath))
                        foundAlbum = relativePath + fileExplorer.PathSeparator + directoryAlbum;
                    //on retire le chemin de base des photos, pour obtenir uniquement le chemin relatif
                    foundAlbum = foundAlbum.Replace(_configurationFile.PhotoFolder, "");
                    //on enlève le caractères séparateur de chemin s'il est présent en début de chaine
                    if (foundAlbum.StartsWith("/") || foundAlbum.StartsWith("\\"))
                        foundAlbum = foundAlbum.Substring(1, foundAlbum.Length - 1);
                    //on ajoute ce chemin à la liste
                    comboBoxAlbum.Items.Add(foundAlbum);
                    //on parcours récursivement dans les sous dossiers
                    FillAlbumComboBox(fileExplorer, directoryAlbum.Contains(relativePath) ? directoryAlbum : relativePath + fileExplorer.PathSeparator + directoryAlbum);
                }
                else
                {
                    //on ajoute ce chemin à la liste
                    comboBoxAlbum.Items.Add(directoryAlbum);
                    //on parcours récursivement dans les sous dossiers
                    FillAlbumComboBox(fileExplorer, directoryAlbum);
                }
            }
        }

        /// <summary>
        /// Charge la form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OptionsDeployAlbulleLoad(object sender, EventArgs e)
        {
            LoadProfilesComboBoxes();
        } 


        #region Private Profiles methods

        /// <summary>
        /// Gère le chargement de la combobox à partir du gestionnaire de profil
        /// </summary>
        private void LoadProfilesComboBoxes()
        {
            //remplissage des combobox contenant les profils de redimensionnement
            int pNormal = comboBoxNormal.SelectedIndex;
            comboBoxNormal.Items.Clear();
            comboBoxNormal.Items.AddRange(_profilesManager.ExistingProfiles.ToArray());
            comboBoxNormal.Items.Add(Resources.ComboBoxSeparator);
            comboBoxNormal.Items.Add(Resources.NewProfile);
            comboBoxNormal.SelectedIndex = pNormal;

            int pOriginal = comboBoxOriginals.SelectedIndex;
            comboBoxOriginals.Items.Clear();
            comboBoxOriginals.Items.AddRange(_profilesManager.ExistingProfiles.ToArray());
            comboBoxOriginals.Items.Add(Resources.ComboBoxSeparator);
            comboBoxOriginals.Items.Add(Resources.NewProfile);
            comboBoxOriginals.SelectedIndex = pOriginal;
        }

        /// <summary>
        /// Gère la sélection d'un élément de la combo box de profils
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ComboBoxProfilesSelectedIndexChanged(object sender, EventArgs e)
        {
            //si le dernier élément est sélectionné ("Nouveau profile...")
            ComboBox combo = (ComboBox)sender;
            if (combo.SelectedIndex == combo.Items.Count - 1)
            {
                NewProfileForm profileForm = new NewProfileForm();
                if (profileForm.ShowDialog() == DialogResult.OK)
                {
                    _profilesManager.AddProfile(profileForm.Profile);
                    LoadProfilesComboBoxes();
                    combo.SelectedIndex = combo.Items.Count - 3;
                }
            }
        }

        /// <summary>
        /// Gère la sélection d'un élément de la combo box des albums
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ComboBoxAlbumSelectedIndexChanged(object sender, EventArgs e)
        {
            //si le dernier élément est sélectionné ("Nouvel album...")
            ComboBox combo = (ComboBox)sender;
            if (combo.SelectedIndex == combo.Items.Count - 1)
            {
                AskNameDialog askAlbumName = new AskNameDialog(Resources.ProcessDialog_ComboBox1SelectedIndexChanged_Nom_du_nouvel_album_, InitialDirectoryOfPicturesToCopy);
                if (askAlbumName.ShowDialog() == DialogResult.OK)
                {
                    comboBoxAlbum.Items.Insert(0, askAlbumName.Result);
                    comboBoxAlbum.SelectedIndex = 0;
                }
                else
                {
                    comboBoxAlbum.SelectedIndex = -1;
                }
            }
        }

        #endregion

        #region Private Output methods
        /// <summary>
        /// Ajoute une sortie
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonAddOutputClick(object sender, EventArgs e)
        {
            //vérification des choix des combo box
            if (checkBoxNormal.Checked && comboBoxNormal.SelectedItem == null)
            {
                MessageBox.Show(Resources.Warn_SelectProfile_Normal);
                return;
            }

            if (checkBoxOriginals.Checked && comboBoxOriginals.SelectedItem == null)
            {
                MessageBox.Show(Resources.Warn_SelectProfile_Originals);
                return;
            }

            //création des output
            if (checkBoxNormal.Checked)
            {
                Output newOut = OutputFactory.Create((Profile)comboBoxNormal.SelectedItem, radioButtonLocal.Checked ? OutputType.Local : OutputType.FTP, _configurationFile.PhotoFolder + comboBoxAlbum.SelectedItem, Connection.Default);
                _selectedOutputs.Add(newOut);
            }
            if (checkBoxThumbnails.Checked)
            {
            }
            if (checkBoxOriginals.Checked)
            {
                Output newOut = OutputFactory.Create((Profile)comboBoxOriginals.SelectedItem, radioButtonLocal.Checked ? OutputType.Local : OutputType.FTP, _configurationFile.OriginalFolder + comboBoxAlbum.SelectedItem, Connection.Default);
                _selectedOutputs.Add(newOut);
            }

            LoadOutputToListbox();
        }

        /// <summary>
        /// Charge la liste des sorties
        /// </summary>
        private void LoadOutputToListbox()
        {
            listViewOutputs.Items.Clear();
            foreach (Output selectedOutput in _selectedOutputs)
            {
                ListViewItem v = new ListViewItem(selectedOutput.Profile.ToString());
                v.SubItems.Add(selectedOutput.Destination.Path);
                v.Tag = selectedOutput;
                listViewOutputs.Items.Add(v);
            }
        } 
        #endregion

        #region Gestion des boutons (Annuler, Mode pas à pas ou mode normal)
        /// <summary>
        /// Gestion du clic sur le bouton Annuler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonCancelClick(object sender, EventArgs e)
        {
            Result = OptionsResults.Cancel;
            Close();
        }

        /// <summary>
        /// Gestion du clic sur le bouton Exécuter en mode pas à pas
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonRunStepClick(object sender, EventArgs e)
        {
            Result = OptionsResults.RunStepToStep;
            Close();
        }

        /// <summary>
        /// Gestion du clic sur le bouton Exécuter en mode normal
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonRunClick(object sender, EventArgs e)
        {
            Result = OptionsResults.RunNormal;
            Close();
        } 
        #endregion
        #endregion   
    }
}
